<?php
namespace app\app\controller\v1;
use think\Db;
use think\Request;
use think\Controller;
use app\app\util\OnlineUtils;
use app\app\model\Users;
require_once(dirname(dirname(dirname(__FILE__))).'/util/php/wxBizDataCrypt.php');
use php\WXBizDataCrypt\WXBizDataCrypt;

class AppController extends Controller{

	/**
	 * [login 授权登录小程序]
	 * @param  Request $request [description]
	 * @return [type]           [description]
	 */
	public function login(Request $request){
		$header = $request->header();
		if( $header['token'] ) {
			//登录过期
			OnlineUtils::OutTime();
		}
		//第一次进入应用
		/**
		 * 3.小程序调用server获取token接口, 传入code, rawData, signature, encryptData.
		 */
		// $param = $request->param();
		$code = input("post.code");
		$rawData = input("post.rawData");
		$signature = input("post.signature");
		$encryptedData = input("post.encryptedData");
		$iv = input("post.iv");
		/**
		 * 4.server调用微信提供的jsoncode2session接口获取openid, session_key, 调用失败应给予客户端反馈
		 * , 微信侧返回错误则可判断为恶意请求, 可以不返回. 微信文档链接
		 * 这是一个 HTTP 接口，开发者服务器使用登录凭证 code 获取 session_key 和 openid。其中 session_key 是对用户数据进行加密签名的密钥。
		 * 为了自身应用安全，session_key 不应该在网络上传输。
		 * 接口地址："https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code"
		 */
		$params = [
			'appid' => CONFIG('APPID'),
			'secret' => CONFIG('SECRET'),
			'js_code' => $code,
			'grant_type' => 'authorization_code'
		];
		$url = "https://api.weixin.qq.com/sns/jscode2session";
		$res = makeRequest($url, $params);
		//result是否存在
		$reqData = json_decode($res);
		// return tof(200,'success',$reqData);
		if (!isset($reqData->session_key)) {
			return jsonReturn('202','未知错误2');
		}
		$sessionKey = $reqData->session_key;

		/**
		 * 5.server计算signature, 并与小程序传入的signature比较, 校验signature的合法性, 不匹配则返回signature不匹配的错误. 不匹配的场景可判断为恶意请求, 可以不返回.
		 * 通过调用接口（如 wx.getUserInfo）获取敏感数据时，接口会同时返回 rawData、signature，其中 signature = sha1( rawData + session_key )
		 *
		 * 将 signature、rawData、以及用户登录态发送给开发者服务器，开发者在数据库中找到该用户对应的 session-key
		 * ，使用相同的算法计算出签名 signature2 ，比对 signature 与 signature2 即可校验数据的可信度。
		 */
		$signature2 = sha1($rawData . $sessionKey);

		if ($signature2 != $signature) return jsonReturn('202','签名错误');

		/**
		 *
		 * 6.使用第4步返回的session_key解密encryptData, 将解得的信息与rawData中信息进行比较, 需要完全匹配,
		 * 解得的信息中也包括openid, 也需要与第4步返回的openid匹配. 解密失败或不匹配应该返回客户相应错误.
		 * （使用官方提供的方法即可）
		 */
		$pc = new WXBizDataCrypt(config('APPID'), $sessionKey);
		$errCode = $pc->decryptData($encryptedData, $iv, $data );

		if ($errCode !== 0) {
			return jsonReturn('202','验证失败');
		}
		$data = json_decode($data);
		//验证通过
		// $unionid = $data['unionid'];
		$openid = $data->openId;
		//获取登录状态，生成登录码
		$encode_code = base64_encode($openid);
		$access_key  = randomFromDev(100,$encode_code);
		//查询用户是否存在
		$user = Db::name('users')->field('id,open_id,nickname,avatar_url,gender')->where('open_id','eq',$openid)->where('status','eq',1)->find();
		if($user){
			$token = md5(time().$user['id']);
			OnlineUtils::sidLogin($token,$user);
			return jsonReturn(200,'success',['token'=>$token,'data'=>$user]); 
		}else{
			// 注册加登录
			$arr = array('open_id'=>$openid,'nickname'=>$data->nickName,'avatar_url'=>$data->avatarUrl,'gender'=>$data->gender);
			//注册时间
			$arr['create_time'] = time();
			$id  = Db::name('users')->insertGetId($arr);
			$arr['id'] = $id;
			//登录
			$token = md5(time().$id);
			OnlineUtils::login($token,$user);
			return jsonReturn(200,'success',['token'=>$token,'data'=>$arr]);
		}	
	}


	//测试专用
	public function test(){
		//强制登录
		$user_id = input('id');
		$sid     = md5(time().$user_id);
		$users   = new Users();
		$user    = $users->get($user_id);
		OnlineUtils::sidLogin($sid,$user);
		return jsonReturn(200,'success',['user'=>$user,'token'=>$sid]);
	}
}